﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLite.Data.Dialect;
using NLite.Data.Dialect.Function;

namespace NLite.Data
{
    public abstract partial class ProjectionNode : Node, IProjectionNode
    {
        public ProjectionNode(NodeType type) : base(type) { }
        public AliasNode As(string alias)
        {
            return new AliasNode(this, alias);
        }
    }

    public partial class ColumnNode : ProjectionNode, IColumnNode
    {
        public string Table { get; private set; }

        public INode Expression { get; set; }

        internal ColumnNode(string columnName, string tableName)
            : base(NodeType.Column)
        {
            this.Table = tableName;
            this.Identity = NameIdentity.Get(SqlTypes.SqlType.Empty, columnName);
        }


        public NameIdentity Identity
        {
            get;
            private set;
        }
    }

    public partial class AggregationNode : ProjectionNode
    {
        public SqlObject Node { get; internal set; }
        public INode Expression { get; internal set; }
        public readonly AggregationOperator Operator;

        public AggregationNode(SqlObject node, INode expression, AggregationOperator op)
            : base(NodeType.Aggregation)
        {
            Node = node;
            Expression = expression;
            Operator = op;
        }
    }

    public partial class CountNode : ProjectionNode
    {
        public SqlObject Column { get; internal set; }
        public Node Criterion { get; internal set; }

        public CountNode(SqlObject column, Node criterion):base(NodeType.Count)
        {
            Column = column;
            Criterion = criterion;
        }
    }

    public sealed partial class AliasNode : Node, IProjectionNode
    {
        public IProjectionNode Projection { get; internal set; }
        public string Alias { get; internal set; }
        public AliasNode(IProjectionNode projection, string alias):base( NodeType.Alias)
        {
            Projection = projection;
            Alias = alias;
        }

        public AliasNode As(string alias)
        {
            Alias = alias;
            return this;
        }
    }


    public partial class FunctionExpression : ProjectionNode,IFunctionNode
    {
        public IFunctionView Function { get; internal set; }
        public INode[] Args { get; internal set; }
        public FunctionExpression(IFunctionView function, params INode[] args)
            : base(NodeType.Function)
        {
            Function = function;
            Args = args;
        }
    }
}
